/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021.
 * Description: Provide functions to obtain and count idle time.
 * Author:xiechengliang
 * Create: 2021-03-30
 */

#include <linux/rtos_idle.h>
#include <linux/cpu.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/percpu.h>
#include <linux/sched.h>

#include "tick-internal.h"

static DEFINE_PER_CPU(struct tick_sched, rtos_tick_cpu_sched);

void tick_idle_enter(void)
{
	struct tick_sched *ts = this_cpu_ptr(&rtos_tick_cpu_sched);

	local_irq_disable();
	ts->idle_entrytime = ktime_get();
	ts->inidle = 1;
	local_irq_enable();
}

void tick_idle_exit(void)
{
	struct tick_sched *ts = this_cpu_ptr(&rtos_tick_cpu_sched);
	ktime_t delta;
	ktime_t now;

	local_irq_disable();
	now = ktime_get();
	delta = ktime_sub(now, ts->idle_entrytime);
	ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
	ts->inidle = 0;
	local_irq_enable();
}

u64 rtos_get_idle_time(int cpu)
{
	struct tick_sched *ts = &per_cpu(rtos_tick_cpu_sched, cpu);
	ktime_t delta = 0;
	ktime_t now;
	u64 idle;

	local_irq_disable();
	if (ts->inidle == 1) {
		now = ktime_get();
		delta = ktime_sub(now, ts->idle_entrytime);
	}
	local_irq_enable();

	delta = ktime_add(ts->idle_sleeptime, delta);
	idle = ktime_to_us(delta);
	idle = idle * NSEC_PER_USEC;
	return idle;
}
